"IFIELD DESCRIPTION, \"\", \"%s\" # FULL_NAME_ND\n"
"IFIELD IGNORE, \"\", \"%s\" # MODIFY_DATE\n"
;
-static char ozi[] =
-"# gpsbabel XCSV style file\n"
-"#\n"
-"# Format: Ozi Explorer\n"
-"# Author: Alex Mottram\n"
-"# Date: 12/09/2002\n"
-"#\n"
-"# \n"
-"# As used in ozi.c\n"
-"# Modifications 9/18/2003 - Remove printf conversion constraints.\n"
-"#\n"
-
-"DESCRIPTION OziExplorer Waypoint\n"
-"EXTENSION ozi\n"
-"SHORTLEN 14\n"
-
-"#\n"
-"# FILE LAYOUT DEFINITIIONS:\n"
-"#\n"
-"FIELD_DELIMITER COMMA\n"
-"RECORD_DELIMITER NEWLINE\n"
-"BADCHARS COMMA\n"
-
-"PROLOGUE OziExplorer Waypoint File Version 1.1\n"
-"PROLOGUE WGS 84\n"
-"PROLOGUE Reserved 2\n"
-"PROLOGUE Reserved 3\n"
-
-"#\n"
-"# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE:\n"
-"#\n"
-"IFIELD INDEX, \"1\", \"%d\"\n"
-"IFIELD SHORTNAME, \"\", \"%s\"\n"
-"IFIELD LAT_DECIMAL, \"\", \"%.6f\"\n"
-"IFIELD LON_DECIMAL, \"\", \"%.6f\"\n"
-"IFIELD EXCEL_TIME, \"\", \"%.5f\"\n"
-"IFIELD CONSTANT, \"0\", \"%s\" # icon \n"
-"IFIELD CONSTANT, \"1\", \"%s\" # 1 \n"
-"IFIELD CONSTANT, \"3\", \"%s\" # display format opts \n"
-"IFIELD CONSTANT, \"0\", \"%s\" # foreground color \n"
-"IFIELD CONSTANT, \"65535\", \"%s\" # background color \n"
-"IFIELD DESCRIPTION, \"\", \"%s\"\n"
-"IFIELD CONSTANT, \"0\", \"%s\" # pointer direction \n"
-"IFIELD CONSTANT, \"0\", \"%s\" # garmin display flags \n"
-"IFIELD CONSTANT, \"0\", \"%s\" # proximity distance \n"
-"IFIELD ALT_FEET, \"\", \"%.0f\"\n"
-"IFIELD CONSTANT, \"6\", \"%s\" # waypt name text size \n"
-"IFIELD CONSTANT, \"0\", \"%s\" # bold checkbox \n"
-"IFIELD CONSTANT, \"17\", \"%s\" # symbol size \n"
-;
static char s_and_t[] =
"# gpsbabel XCSV style file\n"
"#\n"
"IFIELD DESCRIPTION, \"\", \"%-.78s\"\n"
;
#include "defs.h"
-style_vecs_t style_list[] = {{ "xmapwpt", xmapwpt } , { "xmap", xmap } , { "tabsep", tabsep } , { "s_and_t", s_and_t } , { "ozi", ozi } , { "nima", nima } , { "mxf", mxf } , { "mapconverter", mapconverter } , { "gpsman", gpsman } , { "gpsdrive", gpsdrive } , { "fugawi", fugawi } , { "dna", dna } , { "custom", custom } , { "csv", csv } , { "arc", arc } , {0,0}};
+style_vecs_t style_list[] = {{ "xmapwpt", xmapwpt } , { "xmap", xmap } , { "tabsep", tabsep } , { "s_and_t", s_and_t } , { "nima", nima } , { "mxf", mxf } , { "mapconverter", mapconverter } , { "gpsman", gpsman } , { "gpsdrive", gpsdrive } , { "fugawi", fugawi } , { "dna", dna } , { "custom", custom } , { "csv", csv } , { "arc", arc } , {0,0}};
--- /dev/null
+/*
+ OziExplorer Waypoints/Tracks/Routes
+ Comma Delimited
+
+ As described in OziExplorer Help File
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "csv_util.h"
+#include <ctype.h>
+#include <math.h> /* for floor */
+
+#define MYNAME "OZI"
+
+
+static FILE *file_in;
+static FILE *file_out;
+static void *mkshort_handle;
+static route_head *trk_head;
+static route_head *rte_head;
+
+static int route_out_count;
+static int route_wpt_count;
+
+static char *snlenopt;
+static char *snwhiteopt;
+static char *snupperopt;
+static char *snuniqueopt;
+
+static char *ozi_wpt_header = "OziExplorer Waypoint File Version 1.1\n"
+ "WGS 84\n"
+ "Reserved 2\n"
+ "Reserved 3\n";
+
+static char *ozi_trk_header = "OziExplorer Track Point File Version 2.1\n"
+ "WGS 84\n"
+ "Altitude is in Feet\n"
+ "Reserved 3\n"
+ "0,2,255,ComplimentsOfGPSBabel,0,0,2,8421376\n"
+ "0\n";
+
+static char *ozi_route_header = "OziExplorer Route File Version 1.0\n"
+ "WGS 84\n"
+ "Reserved 1\n"
+ "Reserved 2\n";
+
+static
+arglist_t ozi_args[] = {
+ {"snlen", &snlenopt, "Max synthesized shortname length",
+ ARGTYPE_INT},
+ {"snwhite", &snwhiteopt, "(0/1) Allow whitespace synth. shortnames",
+ ARGTYPE_BOOL},
+ {"snupper", &snupperopt, "(0/1) UPPERCASE synth. shortnames",
+ ARGTYPE_BOOL},
+ {"snunique", &snuniqueopt, "(0/1) Make synth. shortnames unique",
+ ARGTYPE_BOOL},
+ {0, 0, 0, 0}
+};
+
+static void
+ozi_track_hdr(const route_head * rte)
+{
+ /* prologue at TOF only. */
+ if (route_out_count == 0)
+ fprintf(file_out, ozi_trk_header);
+
+ route_out_count++;
+}
+
+static void
+ozi_track_disp(const waypoint * waypointp)
+{
+ double alt_feet;
+ double ozi_time;
+
+ ozi_time = (waypointp->creation_time / 86400.0) + 25569.0;
+
+ if (waypointp->altitude == unknown_alt) {
+ alt_feet = -777;
+ } else {
+ alt_feet = (waypointp->altitude * 3.2808);
+ }
+
+ fprintf(file_out, "%.6f,%.6f,0,%.0f,%.5f,,\n",
+ waypointp->latitude, waypointp->longitude, alt_feet, ozi_time);
+}
+
+static void
+ozi_track_tlr(const route_head * rte)
+{
+}
+
+static void
+ozi_track_pr()
+{
+ route_disp_all(ozi_track_hdr, ozi_track_tlr, ozi_track_disp);
+}
+
+static void
+ozi_route_hdr(const route_head * rte)
+{
+ /* prologue on 1st pass only */
+ if (route_out_count == 0) {
+ fprintf(file_out, ozi_route_header);
+ }
+
+ route_out_count++;
+ route_wpt_count = 0;
+
+ /*
+ * Route Record
+ * Field 1 : R - indicating route details
+ * Field 2 : Number - this is the location in the array, must be unique, usually start at 0 for Garmins 1 for other and increment.
+ * Field 3 : Name - the waypoint name, use the correct length name to suit the GPS type.
+ * Field 4 : Description.
+ * Field 5 : Route Color as displayed on map (RGB).
+ *
+ * R, 0,R0 ,,255
+ * R, 1, ICP GALHETA,, 16711680
+ */
+
+ fprintf(file_out, "R,%d,%s,%s,\n",
+ route_out_count,
+ rte->rte_name ? rte->rte_name : "",
+ rte->rte_desc ? rte->rte_desc : "");
+
+}
+
+static void
+ozi_route_disp(const waypoint * waypointp)
+{
+ double alt_feet;
+ double ozi_time;
+
+ route_wpt_count++;
+
+ ozi_time = (waypointp->creation_time / 86400.0) + 25569.0;
+
+ if (waypointp->altitude == unknown_alt) {
+ alt_feet = -777;
+ } else {
+ alt_feet = (waypointp->altitude * 3.2808);
+ }
+
+/*
+ * Field 1 : W - indicating route waypoint details.
+ * Field 2 : Route Number - location in array of routes
+ * Field 3 : Number - this is the location in the array of route waypoints, this field is now ignored.
+ * Field 4 : Wp Number - this is the number of the waypoint (the Wp number within the GPS for lowrances)
+ * Field 5 : Name - the waypoint name, use the correct length name to suit the GPS type.
+ * Field 6 : Latitude - decimal degrees.
+ * Field 7 : Longitude - decimal degrees.
+ * Field 8 : Date - see Date Format below, if blank a preset date will be used
+ * Field 9 : Symbol - 0 to number of symbols in GPS
+ * Field 10 : Status - always set to 1
+ * Field 11 : Map Display Format
+ * Field 12 : Foreground Color (RGB value)
+ * Field 13 : Background Color (RGB value)
+ * Field 14 : Description (max 40), no commas
+ * Field 15 : Pointer Direction
+ * Field 16 : Garmin Display Format
+ *
+ * W,1,7,7,007,-25.581670,-48.316660,36564.54196,10,1,4,0,65535,TR ILHA GALHETA,0,0
+ */
+
+ fprintf(file_out, "W,%d,%d,,%s,%.6f,%.6f,%.5f,0,1,3,0,65535,%s,0,0\n",
+ route_out_count,
+ route_wpt_count,
+ waypointp->shortname ? waypointp->shortname : "",
+ waypointp->latitude,
+ waypointp->longitude,
+ ozi_time,
+ waypointp->description ? waypointp->description : "");
+
+
+}
+
+static void
+ozi_route_tlr(const route_head * rte)
+{
+}
+
+static void
+ozi_route_pr()
+{
+ route_disp_all(ozi_route_hdr, ozi_route_tlr, ozi_route_disp);
+}
+
+
+static void
+rd_init(const char *fname)
+{
+ file_in = fopen(fname, "r");
+
+ if (file_in == NULL) {
+ fatal(MYNAME ": Cannot open %s for reading\n", fname);
+ }
+
+ mkshort_handle = mkshort_new_handle();
+
+ switch (global_opts.objective) {
+ case trkdata:
+ trk_head = route_head_alloc();
+ route_add_head(trk_head);
+ break;
+ case rtedata:
+ break;
+ case wptdata:
+ break;
+ default:
+ break;
+
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+ mkshort_del_handle(mkshort_handle);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = fopen(fname, "w");
+
+ if (file_out == NULL) {
+ fatal(MYNAME ": Cannot open %s for writing\n", fname);
+ }
+
+ mkshort_handle = mkshort_new_handle();
+
+ /* set mkshort options from the command line if applicable */
+ if (global_opts.synthesize_shortnames) {
+
+ if (snlenopt)
+ setshort_length(mkshort_handle, atoi(snlenopt));
+ else
+ setshort_length(mkshort_handle, 32);
+
+ if (snwhiteopt)
+ setshort_whitespace_ok(mkshort_handle, atoi(snwhiteopt));
+
+ if (snupperopt)
+ setshort_mustupper(mkshort_handle, atoi(snupperopt));
+
+ if (snuniqueopt)
+ setshort_mustuniq(mkshort_handle, atoi(snuniqueopt));
+
+ setshort_badchars(mkshort_handle, "\",");
+ }
+
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+ mkshort_del_handle(mkshort_handle);
+}
+
+static void
+ozi_parse_waypt(int field, char *str, waypoint * wpt_tmp)
+{
+ double alt;
+
+ switch (field) {
+ case 0:
+ /* sequence # */
+ break;
+ case 1:
+ /* waypoint name */
+ wpt_tmp->shortname = csv_stringtrim(str, "", 0);
+ break;
+ case 2:
+ /* degrees latitude */
+ wpt_tmp->latitude = atof(str);
+ break;
+ case 3:
+ /* degrees longitude */
+ wpt_tmp->longitude = atof(str);
+ break;
+ case 4:
+ /* DAYS since 1900 00:00:00 in days.days (5.5) */
+ wpt_tmp->creation_time = (atof(str) - 25569.0) * 86400.0;
+ break;
+ case 5:
+ /* icons 0-xx */
+ break;
+ case 6:
+ /* unknown - always 1 */
+ break;
+ case 7:
+ /* display format options 0-8 */
+ break;
+ case 8:
+ /* foreground color (0=black) */
+ break;
+ case 9:
+ /* background color (65535=yellow) */
+ break;
+ case 10:
+ /* Description */
+ wpt_tmp->description = csv_stringtrim(str, "", 0);
+ break;
+ case 11:
+ /* pointer direction 0,1,2,3 bottom,top,left,right */
+ break;
+ case 12:
+ /* garmin gps display flags (0-name w/sym, 1-sym only, 2-comment w/symbol */
+ break;
+ case 13:
+ /* proximity distance - meters */
+ break;
+ case 14:
+ /* altitude in feet */
+ alt = atof(str);
+ if (alt == -777) {
+ wpt_tmp->altitude = unknown_alt;
+ } else {
+ wpt_tmp->altitude = alt * .3048;
+ }
+ break;
+ case 15:
+ /* waypoint text name size */
+ break;
+ case 16:
+ /* bold checkbox (1=bold, default 0) */
+ break;
+ case 17:
+ /* symbol size - 17 default */
+ break;
+ /*
+ * Fields 18-23 were added around version 3.90.4g of
+ * Ozi, but aren't documented. We silently ignore
+ * these or any additional fields we don't need.
+ */
+ default:
+ break;
+ }
+}
+
+static void
+ozi_parse_track(int field, char *str, waypoint * wpt_tmp)
+{
+ double alt;
+
+ switch (field) {
+ case 0:
+ /* latitude */
+ wpt_tmp->latitude = atof(str);
+ break;
+ case 1:
+ /* longitude */
+ wpt_tmp->longitude = atof(str);
+ break;
+ case 2:
+ /* ignore */
+ break;
+ case 3:
+ /* altitude in feet */
+ alt = atof(str);
+ if (alt == -777) {
+ wpt_tmp->altitude = unknown_alt;
+ } else {
+ wpt_tmp->altitude = alt * .3048;
+ }
+ break;
+ case 4:
+ /* DAYS since 1900 00:00:00 in days.days (5.5) */
+ wpt_tmp->creation_time = (atof(str) - 25569.0) * 86400.0;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ozi_parse_routepoint(int field, char *str, waypoint * wpt_tmp)
+{
+
+ switch (field) {
+ case 0:
+ /* W */
+ break;
+ case 1:
+ /* route # */
+ break;
+ case 2:
+ /* waypoint # -- ignored by ozi */
+ break;
+ case 3:
+ /* waypoint # */
+ break;
+ case 4:
+ /* waypoint name */
+ wpt_tmp->shortname = csv_stringclean(str, ",");
+ break;
+ case 5:
+ /* latitude */
+ wpt_tmp->latitude = atof(str);
+ break;
+ case 6:
+ /* longitude */
+ wpt_tmp->longitude = atof(str);
+ break;
+ case 7:
+ /* DAYS since 1900 00:00:00 in days.days (5.5) */
+ wpt_tmp->creation_time = (atof(str) - 25569.0) * 86400.0;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ozi_parse_routeheader(int field, char *str, waypoint * wpt_tmp)
+{
+
+ switch (field) {
+ case 0:
+ /* R */
+ rte_head = route_head_alloc();
+ route_add_head(rte_head);
+ break;
+ case 1:
+ /* route # */
+ rte_head->rte_num = atoi(str);
+ break;
+ case 2:
+ /* route name */
+ rte_head->rte_name = csv_stringclean(str, ",");
+ break;
+ case 3:
+ /* route description */
+ rte_head->rte_desc = csv_stringclean(str, ",");
+ break;
+ case 4:
+ /* route color */
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+data_read(void)
+{
+ char buff[1024];
+ char *s;
+ waypoint *wpt_tmp;
+ int i;
+ int linecount = 0;
+
+ do {
+ linecount++;
+ memset(buff, '\0', sizeof(buff));
+ fgets(buff, sizeof(buff), file_in);
+
+ if ((strlen(buff)) && (strstr(buff, ",") != NULL)) {
+
+ wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1);
+
+ /* data delimited by commas, possibly enclosed in quotes. */
+ s = buff;
+ s = csv_lineparse(s, ",", "", linecount);
+
+ i = 0;
+ while (s) {
+ switch (global_opts.objective) {
+ case trkdata:
+ ozi_parse_track(i, s, wpt_tmp);
+ break;
+ case rtedata:
+ if (buff[0] == 'R') {
+ ozi_parse_routeheader(i, s, wpt_tmp);
+ } else {
+ ozi_parse_routepoint(i, s, wpt_tmp);
+ }
+
+ break;
+ case wptdata:
+ ozi_parse_waypt(i, s, wpt_tmp);
+ break;
+ }
+ i++;
+ s = csv_lineparse(NULL, ",", "", linecount);
+ }
+
+ switch (global_opts.objective) {
+ case trkdata:
+ if (linecount > 6) /* skipping over file header */
+ route_add_wpt(trk_head, wpt_tmp);
+ else
+ waypt_free(wpt_tmp);
+ break;
+ case rtedata:
+ if (linecount > 5) /* skipping over file header */
+ route_add_wpt(rte_head, wpt_tmp);
+ else
+ waypt_free(wpt_tmp);
+ break;
+ case wptdata:
+ if (linecount > 4) /* skipping over file header */
+ waypt_add(wpt_tmp);
+ else
+ waypt_free(wpt_tmp);
+ break;
+ }
+
+ } else {
+ /* empty line */
+ }
+
+ } while (!feof(file_in));
+}
+
+static void
+ozi_waypt_pr(const waypoint * wpt)
+{
+ static int index = 0;
+ double alt_feet;
+ double ozi_time;
+ char *description;
+ char *shortname;
+
+ ozi_time = (wpt->creation_time / 86400.0) + 25569.0;
+
+ if (wpt->altitude == unknown_alt) {
+ alt_feet = -777;
+ } else {
+ alt_feet = (wpt->altitude * 3.2808);
+ }
+
+ if ((!wpt->shortname) || (global_opts.synthesize_shortnames)) {
+ if (wpt->description) {
+ if (global_opts.synthesize_shortnames)
+ shortname = mkshort(mkshort_handle, wpt->description);
+ else
+ shortname = csv_stringclean(wpt->description, ",");
+ } else {
+ /* no description available */
+ shortname = xstrdup("");
+ }
+ } else {
+ shortname = csv_stringclean(wpt->shortname, ",");
+ }
+
+ if (!wpt->description) {
+ if (shortname) {
+ description = csv_stringclean(shortname, ",");
+ } else {
+ description = xstrdup("");
+ }
+ } else {
+ description = csv_stringclean(wpt->description, ",");
+ }
+
+ index++;
+
+ fprintf(file_out,
+ "%d,%s,%.6f,%.6f,%.5f,%d,%d,%d,%d,%d,%s,%d,%d,%d,%.0f,%d,%d,%d\n",
+ index, shortname, wpt->latitude, wpt->longitude, ozi_time, 0,
+ 1, 3, 0, 65535, description, 0, 0, 0, alt_feet, 6, 0, 17);
+
+ free(description);
+ free(shortname);
+
+}
+
+static void
+data_write(void)
+{
+
+ switch (global_opts.objective) {
+ case trkdata:
+ ozi_track_pr();
+ break;
+ case rtedata:
+ route_out_count = 0;
+ ozi_route_pr();
+ break;
+ case wptdata:
+ fprintf(file_out, ozi_wpt_header);
+ waypt_disp_all(ozi_waypt_pr);
+ break;
+ default:
+ break;
+ }
+}
+
+ff_vecs_t ozi_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ ozi_args
+};